import time
import can
import serial
import os
import binascii
import codecs


def can_open():  # 开启can通讯
    os.system('sudo ip link set can0 type can bitrate 250000')
    os.system('sudo ifconfig can0 up')


# channel_name为do的位置，如果输入0则为操作全部，switch是开光状态0为关，1为开
def can_relay_board_do_control(channel_name, switch):
    # 设置CAN接口（请替换为你的CAN接口）
    can_interface = "can0"
    # 设置CAN消息的ID和数据（请替换为你的实际值）
    can_id = 0x0101
    if switch not in {0, 1}:
        print("Error: Invalid value for switch. It must be 0 or 1.")
        return None

    if not isinstance(channel_name, int) or channel_name < 0 or channel_name > 255:
        print("Error: Invalid value for channel_name. It must be a number between 0 and 255.")
        return None
    channel_byte = [channel_name & 0xFF]
    switch_byte = [switch & 0xFF]

    can_data = [eval('0x{:02X}'.format(channel_byte[0])), eval('0x{:02X}'.format(switch_byte[0])), 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00]

    # 创建CAN总线对象
    bus = can.interface.Bus(channel=can_interface, bustype='socketcan')

    # 创建CAN消息对象
    message = can.Message(arbitration_id=can_id, data=can_data, is_extended_id=False)

    try:
        # 发送CAN消息
        bus.send(message)
        message_read = bus.recv(timeout=1)  # 接收数据
        # print(f"Sent CAN message: {message}")
        if message_read is not None:
            # print(f"Read CAN message: {message_read.data}")
            # print(f"Read CAN message ID: {message_read.arbitration_id}")
            print("can通讯正常")
        else:
            print("can通讯故障")
    except can.CanError:
        print("can通道未打开")


def Obtain_485_data(Serial_channel, Sending_instructions):
    # 第一位为串口通道，第二位为发送指令,输入串口通道和具体485指令如果正确会返回设备的回复帧,
    # 输入示例result = Obtain_485_data(inverter_status_and_cems_status, "01030000000EC40E")
    Sending_frequency = 1
    return_data = b''
    while Sending_frequency <= 1:
        Sending_instructions_bytes = codecs.decode(Sending_instructions, 'hex')
        Serial_channel.write(Sending_instructions_bytes)
        Sending_frequency += 1
        time.sleep(1)
        if Serial_channel.inWaiting():
            available_bytes = Serial_channel.inWaiting()
            return_data = binascii.b2a_hex(Serial_channel.read(available_bytes))
            # print(return_data)
    return return_data.decode('utf-8')


def serial_test(ser_channel):
    # 打开串口设备文件
    if 'ser' in globals() and ser.is_open:
        ser.close()
    ser_channel.flushInput()

    s = "page homepage"
    # 字符串变gbk字符型字节流
    s_byte = s.encode("gbk")
    # 字符型字节流转十六进制字节流, 与b2a_hex()，bytes.hex()方法功能一样
    s_hex = binascii.hexlify(s_byte)
    s_hex = s_hex + b'FFFFFF'
    # 十六进制字节流解码
    s_gbk = codecs.decode(s_hex, 'hex')
    ser_channel.write(s_gbk)
    ser_channel.close()


if __name__ == "__main__":
    # 操作示例
    can_open()
    # can_relay_board_do_control(0, 1)  # 开启全部
    # time.sleep(1)
    # can_relay_board_do_control(0, 0)  # 关闭全部
    # time.sleep(1)
    # can_relay_board_do_control(1, 1)  # 开启通道1
    # time.sleep(1)
    # can_relay_board_do_control(1, 0)  # 关闭通道1
    # time.sleep(1)
    # can_relay_board_do_control(2, 1)  # 开启通道2
    # time.sleep(1)
    # can_relay_board_do_control(2, 0)  # 关闭通道2
    # for i in range(1, 25):
    #     can_relay_board_do_control(i, 1)
    #     time.sleep(1)
    #     print(i)
    # for i in range(1, 25):
    #     can_relay_board_do_control(i, 0)
    #     time.sleep(1)
    #     print(i)
    communication_channel_485 = serial.Serial("/dev/ttyS0", 9600)
    communication_channel_ser = serial.Serial("/dev/ttySC0", 9600)

    result_485 = Obtain_485_data(communication_channel_485, "01040000000271CB")
    if not result_485:
        print("485通讯故障")
    else:
        print("485通讯正常")
    can_relay_board_do_control(0, 0)  # 关闭全部,can通讯测试
    serial_test(communication_channel_ser)
